From f9ef80600b07d0eab56a5b913d0d2c1d61b55feb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 28 Feb 2006 10:18:34 +0100 Subject: [PATCH] Fix a multi HVM domain issue (bugzilla bug #542): This issue can be reproduced on SMP platform, while the domain 0 is UP. The reason is, after finishing a dma request, the dma thread will trigger the interrupt and then clear the call back function. When guest get the interrupt , it will try to check the call back function, if it is set, then it will trigger a dma request again. So if the checking for the callbackfunction happens between trigger interrupt and clear callback function on dma thread, it will cause NULL function calling. After with domain 0 UP and smp platform, this situation can be reproduced easily. Signed-off-by: Yunhong Jiang --- tools/ioemu/hw/ide.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index 7c012cebcb..7ed0815da6 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -669,9 +669,6 @@ static int ide_read_dma_cb(IDEState *s, } if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) { s->status = READY_STAT | SEEK_STAT; - s->bmdma->status &= ~BM_STATUS_DMAING; - s->bmdma->status |= BM_STATUS_INT; - ide_set_irq(s); #ifdef DEBUG_IDE_ATAPI printf("dma status=0x%x\n", s->status); #endif @@ -738,9 +735,6 @@ static int ide_write_dma_cb(IDEState *s, if (n == 0) { /* end of transfer */ s->status = READY_STAT | SEEK_STAT; - s->bmdma->status &= ~BM_STATUS_DMAING; - s->bmdma->status |= BM_STATUS_INT; - ide_set_irq(s); return 0; } if (n > MAX_MULT_SECTORS) @@ -987,9 +981,6 @@ static int ide_atapi_cmd_read_dma_cb(IDEState *s, if (s->packet_transfer_size <= 0) { s->status = READY_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; - s->bmdma->status &= ~BM_STATUS_DMAING; - s->bmdma->status |= BM_STATUS_INT; - ide_set_irq(s); #ifdef DEBUG_IDE_ATAPI printf("dma status=0x%x\n", s->status); #endif @@ -2025,6 +2016,17 @@ static void ide_map(PCIDevice *pci_dev, int region_num, } } +static void ide_dma_finish(BMDMAState *bm) +{ + IDEState *s = bm->ide_if; + + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + ide_set_irq(s); +} + /* XXX: full callback usage to prepare non blocking I/Os support - error handling */ #ifdef DMA_MULTI_THREAD @@ -2070,9 +2072,8 @@ static void ide_dma_loop(BMDMAState *bm) cur_addr += 8; } /* end of transfer */ - the_end: - bm->dma_cb = NULL; - bm->ide_if = NULL; +the_end: + ide_dma_finish(bm); } static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb) -- 2.30.2